﻿/*
  XhrHTML5 for Monkey

  Written by Sébastien Guillemette (Alias Rushino)

  -> Module that enable you to send XmlHttpRequest (Level 2) on the HTML 5 build platform of Monkey.

  Copyright(C) 2012 Sébastien Guillemette

  Permission is hereby granted, free of charge, To any person obtaining a copy of this software and associated documentation files
  (the "Software"), To deal in the Software without restriction, including without limitation the rights To use, copy, modify, merge,
  publish, distribute, sublicense, and / or sell copies of the Software, and To permit persons To whom the Software is furnished To do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  FITNESS For A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE For ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/* The object instance in represented in Monkey. */
function XhrObject()
{
	this.Reset();
};

XhrObject.prototype.Reset = function()
{
	this.state = 0;				// State of the request.
								/*
								  0 = Uninitialized		The object has been created, but not initialized (the open method has not been called).
								  1 = Loading			A request has been opened, but the send method has not been called.
								  2 = Loaded			The send method has been called. No data is available yet.
								  3 = Interactive		Some data has been received; however, neither responseText nor responseBody is available.
								  4 = Complete			All the data has been received.
								*/
								
	this.serverStatusCode = 0;	// Server code status.
	this.status = 0;			/* Status of the request. 
							      0 = Idle						Waiting for a request.
								  1 = Connected					A request has been opened, but the send method has not been called.
							  	  2 = Request sent				The send method has been called. No data is available yet.
								  3 = Started receiving data	Some data has been received; however, neither responseText nor responseBody is available.
								  4 = Done receiving data		All the data has been received.
								  5 = Success					The request is a success.
								  6 = Error						An error occured during the request.
								  7 = Timeout					A timeout occured.
								*/
	this.result = "";		
	this.message = "";		
	this.xmlResult = "";
	this.percentCompleted = 0;
};

function UpdateInstanceStatus(event) {
	event.target.instance.result = event.target.responseText;
	event.target.instance.xmlResult = event.target.responseXML;
	event.target.instance.serverStatusCode = event.target.status;
	event.target.instance.message = event.target.statusText;
	event.target.instance.state = event.target.readyState;
};

/* A function to instanciate the XmlHttpRequest object. */
function getXMLHttpRequest() {
	var xhr = new XMLHttpRequest();
	return xhr;
};

/* A function to send a GET request with a timeout. */
XhrObject.prototype.Get = function( url, timeoutConnection )
{
    /* Create a new XmlHttpRequest. */
	this.xhr = getXMLHttpRequest();
	
	/* This set the monkey instance to the XmlHttpRequest object so we don't lose it. */
	this.xhr.instance = this;
	
	/* Execute when the request have been a success. */
	var onLoadHandler = function(event) {
    	UpdateInstanceStatus(event);
		event.target.instance.status = 5;
		event.target.instance.OnRequestSuccess(event.target.responseText);
	}
	
	/* Execute when the request failed. */
	var onError = function(event) {
		UpdateInstanceStatus(event);
		event.target.instance.status = 6;
		event.target.instance.message = "Couldn't not execute the open() command or an error occured!";
		event.target.instance.OnRequestError();
	}
	
	/* Execute when a timeout occurs. */
	var onTimeOutHandler = function(event) {
		event.target.timeout = timeoutConnection;
	    event.target.open('GET', url, true);
	    UpdateInstanceStatus(event);
		event.target.send();
		event.target.instance.status = 7;
		event.target.instance.OnRequestTimeout();
     }
	 
	 /* Execute during the progess of the request. */
	 var onProgressHandler = function(event) {
		  // Calculate progress.
		  if (event.lengthComputable) {
		     event.target.instance.percentCompleted = 100 * event.loaded / event.total;
		  }
		  UpdateInstanceStatus(event);
	 }

	 /* Handle ready states of the request. */
	 var onReadyStateHandler = function(event) {
		  UpdateInstanceStatus(event);
		  event.target.instance.status = event.target.readyState;
		  
		  // Trigger event based on the status of the request.
		  switch (event.target.readyState) {
		  case 1:
		  	event.target.instance.OnConnectionEstablished();
		    break;
		  case 2:
		  	event.target.instance.OnRequestReceived();
		    break;
		  case 3:
		  	event.target.instance.OnRequestProcessing();
		    break;
		  case 4:
		  	event.target.instance.OnRequestComplete();
		    break;
		  }
	 }

     this.xhr.open('GET', url, true);
	 this.xhr.timeout = timeoutConnection;
	 this.xhr.onload = onLoadHandler;
	 this.xhr.onerror = onError;
	 this.xhr.ontimeout = onTimeOutHandler;
	 this.xhr.onprogress = onProgressHandler;
	 this.xhr.onreadystatechange = onReadyStateHandler;
	 this.xhr.send();
};

XhrObject.prototype.Post = function(url, args, timeoutConnection )
{
	/* Create a new XmlHttpRequest. */
	this.xhr = getXMLHttpRequest();
	
	/* This set the monkey instance to the XmlHttpRequest object so we don't lose it. */
	this.xhr.instance = this;
	
	/* Create a new FormData object. */
	var dataToSend = new FormData();
	
	/* Execute when the request have been a success. */
	var onLoadHandler = function(event) {
    	UpdateInstanceStatus(event);
		event.target.instance.status = 5;
		event.target.instance.OnRequestSuccess(event.target.responseText);
	}
	
	/* Execute when the request failed. */
	var onError = function(event) {
		UpdateInstanceStatus(event);
		event.target.instance.status = 6;
		event.target.instance.message = "Couldn't not execute the open() command or an error occured!";
		event.target.instance.OnRequestError();
	}
	
	/* Execute when a timeout occurs. */
	var onTimeOutHandler = function(event) {
		event.target.timeout = timeoutConnection;
	    event.target.open('POST', url, true);
	    UpdateInstanceStatus(event);
		event.target.send(dataToSend);
		event.target.instance.status = 7;
		event.target.instance.OnRequestTimeout();
     }
	 
	 /* Execute during the progess of the request. */
	 var onProgressHandler = function(event) {
		  // Calculate progress.
		  if (event.lengthComputable) {
		     event.target.instance.percentCompleted = 100 * event.loaded / event.total;
		  }
		  UpdateInstanceStatus(event);
	 }

	 /* Handle ready states of the request. */
	 var onReadyStateHandler = function(event) {
		  UpdateInstanceStatus(event);
		  event.target.instance.status = event.target.readyState;
		  
		  // Trigger event based on the status of the request.
		  switch (event.target.readyState) {
		  case 1:
		  	event.target.instance.OnConnectionEstablished();
		    break;
		  case 2:
		  	event.target.instance.OnRequestReceived();
		    break;
		  case 3:
		  	event.target.instance.OnRequestProcessing();
		    break;
		  case 4:
		  	event.target.instance.OnRequestComplete();
		    break;
		  }
	 }

     this.xhr.open('POST', url, true);
	
	 /* Append POST data. */
	 var dataArray = args.split(",");
	 for(var i=0;i<dataArray.length;i++)
	 {
	 	var currentParam = dataArray[i].split(":");
		dataToSend.append(currentParam[0],currentParam[1]);
	 }

	 this.xhr.timeout = timeoutConnection;
	 this.xhr.onload = onLoadHandler;
	 this.xhr.onerror = onError;
	 this.xhr.ontimeout = onTimeOutHandler;
	 this.xhr.onprogress = onProgressHandler;
	 this.xhr.onreadystatechange = onReadyStateHandler;
	 this.xhr.send(dataToSend);
};

XhrObject.prototype.GetServerStatusCode = function()
{
	return this.serverStatusCode;
};

XhrObject.prototype.GetStatus = function()
{
	return this.status;
};

XhrObject.prototype.GetRequestState = function()
{
	return this.state;
};

XhrObject.prototype.GetResult = function()
{
	return this.result;
};

XhrObject.prototype.GetMessage = function()
{
	return this.message;
};

XhrObject.prototype.IsSuccess = function()
{
	return this.status == 5;
};

XhrObject.prototype.IsFailure = function()
{
	return this.status == 6;
};

XhrObject.prototype.OnRequestError = function() {};
XhrObject.prototype.OnRequestSuccess = function(response) {};
XhrObject.prototype.OnRequestReceived = function() {};
XhrObject.prototype.OnRequestProcessing = function() {};
XhrObject.prototype.OnRequestComplete = function() {};
XhrObject.prototype.OnConnectionEstablished = function() {};
XhrObject.prototype.OnRequestTimeout = function() {};
